﻿namespace FrameWork.Lib.HTML
{
    using System;
    using System.ComponentModel;

    public abstract class HtmlNode
    {
        protected HtmlElement mParent = null;

        protected HtmlNode()
        {
        }

        [Category("Relationships")]
        public HtmlNode GetCommonAncestor(HtmlNode node)
        {
            for (HtmlNode node2 = this; node2 != null; node2 = node2.Parent)
            {
                for (HtmlNode node3 = node; node3 != null; node3 = node3.Parent)
                {
                    if (node2 == node3)
                    {
                        return node2;
                    }
                }
            }
            return null;
        }

        [Category("Relationships")]
        public bool IsAncestorOf(HtmlNode node)
        {
            return node.IsDescendentOf(this);
        }

        [Category("Relationships")]
        public bool IsDescendentOf(HtmlNode node)
        {
            for (HtmlNode node2 = this.mParent; node2 != null; node2 = node2.Parent)
            {
                if (node2 == node)
                {
                    return true;
                }
            }
            return false;
        }

        [Description("This is true if this is an element node"), Category("General")]
        public bool IsElement()
        {
            return (this is HtmlElement);
        }

        [Category("General"), Description("This is true if this is a text node")]
        public bool IsText()
        {
            return (this is HtmlText);
        }

        [Category("General")]
        public void Remove()
        {
            if (this.mParent != null)
            {
                this.mParent.Nodes.RemoveAt(this.Index);
            }
        }

        internal void SetParent(HtmlElement parentNode)
        {
            this.mParent = parentNode;
        }

        public abstract override string ToString();

        [Description("The first child of this node"), Category("Navigation")]
        public HtmlNode FirstChild
        {
            get
            {
                if (this is HtmlElement)
                {
                    if (((HtmlElement) this).Nodes.Count == 0)
                    {
                        return null;
                    }
                    return ((HtmlElement) this).Nodes[0];
                }
                return null;
            }
        }

        [Category("Output"), Description("The HTML that represents this node and all the children")]
        public abstract string HTML { get; }

        [Category("Navigation"), Description("The zero-based index of this node in the parent's nodes collection")]
        public int Index
        {
            get
            {
                if (this.mParent == null)
                {
                    return -1;
                }
                return this.mParent.Nodes.IndexOf(this);
            }
        }

        [Description("Is this node a child of another?"), Category("Navigation")]
        public bool IsChild
        {
            get
            {
                return (this.mParent != null);
            }
        }

        [Category("Navigation"), Description("Does this node have any children?")]
        public bool IsParent
        {
            get
            {
                return ((this is HtmlElement) && (((HtmlElement) this).Nodes.Count > 0));
            }
        }

        [Description("Is this node a root node?"), Category("Navigation")]
        public bool IsRoot
        {
            get
            {
                return (this.mParent == null);
            }
        }

        [Description("The last child of this node"), Category("Navigation")]
        public HtmlNode LastChild
        {
            get
            {
                if (this is HtmlElement)
                {
                    if (((HtmlElement) this).Nodes.Count == 0)
                    {
                        return null;
                    }
                    return ((HtmlElement) this).Nodes[((HtmlElement) this).Nodes.Count - 1];
                }
                return null;
            }
        }

        [Category("Navigation"), Description("The next sibling node")]
        public HtmlNode Next
        {
            get
            {
                if ((this.Index != -1) && (this.Parent.Nodes.Count > (this.Index + 1)))
                {
                    return this.Parent.Nodes[this.Index + 1];
                }
                return null;
            }
        }

        [Description("The parent node of this one"), Category("Navigation")]
        public HtmlElement Parent
        {
            get
            {
                return this.mParent;
            }
        }

        [Category("Navigation"), Description("The previous sibling node")]
        public HtmlNode Previous
        {
            get
            {
                if ((this.Index != -1) && (this.Index > 0))
                {
                    return this.Parent.Nodes[this.Index - 1];
                }
                return null;
            }
        }

        [Description("The XHTML that represents this node and all the children"), Category("Output")]
        public abstract string XHTML { get; }
    }
}

